home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / UNIX / PASCAL / PTOC / PTC_P.3 < prev    next >
Text File  |  1992-11-23  |  50KB  |  2,502 lines

  1.                     tx^.tto := ty^.thi
  2.                     end
  3.                 else if ty^.tt = nscalar then
  4.                     begin
  5.                     ty := ty^.tscalid;
  6.                     tx^.tfrom := ty;
  7.                     while ty^.tnext <> nil do
  8.                         ty := ty^.tnext;
  9.                     tx^.tto := ty
  10.                     end
  11.                 else if ty = typnods[tchar] then
  12.                     begin
  13.                     currsym.st := schar;
  14.                     currsym.vchr := chr(minchar);
  15.                     tx^.tfrom := mklit;
  16.                     currsym.st := schar;
  17.                     currsym.vchr := chr(maxchar);
  18.                     tx^.tto := mklit
  19.                     end
  20.                 else if ty = typnods[tinteger] then
  21.                     begin
  22.                     currsym.st := sinteger;
  23.                     currsym.vint := -maxint;
  24.                     tx^.tfrom := mklit;
  25.                     currsym.st := sinteger;
  26.                     currsym.vint := maxint;
  27.                     tx^.tto := mklit
  28.                     end
  29.                 else
  30.                     fatal(etree);
  31.                 tx^.tforstmt := tz;
  32.                 tx^.tincr := true
  33.                 end;
  34.               npredef,
  35.               nfileof:
  36.                 if opn then
  37.                     begin
  38.                     (* create file-struct initialization *)
  39.                     ty := mknode(nselect);
  40.                     ty^.trecord := ti;
  41.                     ty^.tfield :=
  42.                         oldid(defnams[dzinit]^.lid,
  43.                                 lforward);
  44.                     tx := mknode(nassign);
  45.                     tx^.tlhs := ty;
  46.                     currsym.st := sinteger;
  47.                     currsym.vint := 0;
  48.                     tx^.trhs := mklit
  49.                     end
  50.                 else begin
  51.                     (* create file-struct wrapup *)
  52.                     tx := mknode(ncall);
  53.                     tx^.tcall := 
  54.                         oldid(defnams[dclose]^.lid,
  55.                                 lidentifier);
  56.                     tx^.taparm := ti
  57.                      end;
  58.               nrecord:
  59.                 begin
  60.                 ty := nil;
  61.                 tq := tq^.tflist;
  62.                 while tq <> nil do
  63.                     begin
  64.                     if filevar(typeof(tq^.tbind)) then
  65.                         begin
  66.                         tz := tq^.tidl;
  67.                         while tz <> nil do
  68.                             begin
  69.                             tx := mknode(nselect);
  70.                             tx^.trecord := ti;
  71.                             tx^.tfield := tz;
  72.                             tx := fileinit(tx,
  73.                                 typeof(tq^.tbind),
  74.                                 opn);
  75.                             tx^.tnext := ty;
  76.                             ty := tx;
  77.                             tz := tz^.tnext
  78.                             end
  79.                         end;
  80.                     tq := tq^.tnext
  81.                     end;
  82.                 tx := mknode(nbegin);
  83.                 tx^.tbegin := ty
  84.                 end;
  85.             end;(* case *)
  86.             fileinit := tx
  87.         end;
  88.  
  89.     begin    (* initcode *)
  90.         while tp <> nil do
  91.             begin
  92.             initcode(tp^.tsubsub);
  93.             tv := tp^.tsubvar;
  94.             while tv <> nil do
  95.                 begin
  96.                 tq := typeof(tv^.tbind);
  97.                 if filevar(tq) then
  98.                     begin
  99.                     ti := tv^.tidl;
  100.                     while ti <> nil do
  101.                         begin
  102.                         tu := fileinit(ti, tq, true);
  103.                         linkup(tp, tu);
  104.                         tu^.tnext := tp^.tsubstmt;
  105.                         tp^.tsubstmt := tu;
  106.                         while tu^.tnext <> nil do
  107.                             tu := tu^.tnext;
  108.                         tu^.tnext := fileinit(ti, tq,
  109.                                     false);
  110.                         linkup(tp, tu^.tnext);
  111.                         ti := ti^.tnext
  112.                         end
  113.                     end;
  114.                 tv := tv^.tnext;
  115.                 end;
  116.             tp := tp^.tnext
  117.             end
  118.     end;    (* initcode *)
  119.  
  120. begin    (* transform *)
  121.     renamc;
  122.     renamp(top^.tsubsub, false);
  123.     extract(top);
  124.     renamf(top);
  125.     initcode(top^.tsubsub);
  126.     global(top, top, false)
  127. end;    (* transform *)
  128.  
  129. (*    Emit C-code for program or module.                *)
  130. procedure emit;
  131.  
  132. const    include    = '# include ';
  133.     define    = '# define ';
  134.     ifdef    = '# ifdef ';
  135.     ifndef    = '# ifndef ';
  136.     elsif    = '# else';
  137.     endif    = '# endif';
  138.     static    = 'static ';
  139.     xtern    = 'extern ';
  140.     typdef    = 'typedef ';
  141.     registr    = 'register ';
  142.     usigned    = 'unsigned ';
  143.     indstep    = 8;
  144.  
  145. var    conflag,
  146.     setused,
  147.     dropset,
  148.     donearr    : boolean;
  149.     doarrow,
  150.     indnt    : integer;
  151.  
  152.     procedure increment;
  153.     begin
  154.         indnt := indnt + indstep
  155.     end;
  156.  
  157.     procedure decrement;
  158.     begin
  159.         indnt := indnt - indstep
  160.     end;
  161.  
  162.     (*    Write tabs/blanks to properly (?) indent C-code.    *) 
  163.     procedure indent;
  164.  
  165.     var    i    : integer;
  166.  
  167.     begin
  168.         i := indnt;
  169.         (* limit indent to an integral number of tabs *)
  170.         if i > 60 then
  171.             i := i div tabwidth * tabwidth;
  172.         while i >= tabwidth do
  173.             begin
  174.             write(tab1);
  175.             i := i - tabwidth
  176.             end;
  177.         while i > 0 do
  178.             begin
  179.             write(space);
  180.             i := i - 1
  181.             end;
  182.     end;
  183.  
  184.     (*    Determine if tp must be cast to an integer before being    *)
  185.     (*    used in an arithmetic expression.            *)
  186.     function arithexpr(tp : treeptr) : boolean;
  187.  
  188.     begin
  189.         tp := typeof(tp);
  190.         if tp^.tt = nsubrange then
  191.             if tp^.tup^.tt = nconfarr then
  192.                 tp := typeof(tp^.tup^.tindtyp)
  193.             else
  194.                 tp := typeof(tp^.tlo);
  195.         arithexpr := (tp = typnods[tinteger]) or
  196.                 (tp = typnods[tchar]) or
  197.                     (tp = typnods[treal])
  198.     end;
  199.  
  200.     procedure eexpr(tp : treeptr);                forward;
  201.     procedure etypedef(tp : treeptr);            forward;
  202.  
  203.     (*    Emit code to select a record member.    *)
  204.     procedure eselect(tp : treeptr);
  205.  
  206.     begin
  207.         doarrow := doarrow + 1;
  208.         eexpr(tp);
  209.         doarrow := doarrow - 1;
  210.         if donearr then
  211.             donearr := false
  212.         else
  213.             write('.')
  214.     end;
  215.  
  216.     (*    Emit code for call to a predefined function/procedure.    *)
  217.     procedure epredef(ts, tp : treeptr);
  218.  
  219.     label    444, 555;
  220.  
  221.     var    tq,
  222.         tv, tx    : treeptr;
  223.         td    : predefs;
  224.         nelems    : integer;
  225.         ch    : char;
  226.         txtfile    : boolean;
  227.  
  228.         (*    Determine a format-code for fprintf.        *)
  229.         (*    Update nelems as a sideeffect.            *)
  230.         function typeletter(tp : treeptr) : char;
  231.  
  232.         label    999;
  233.  
  234.         var    tq    : treeptr;
  235.  
  236.         begin
  237.             tq := tp;
  238.             if tq^.tt = nformat then
  239.                 begin
  240.                 if tq^.texpl^.tt = nformat then
  241.                     begin
  242.                     typeletter := 'f';
  243.                     goto 999
  244.                     end;
  245.                 tq := tp^.texpl
  246.                 end;
  247.             tq := typeof(tq);
  248.             if tq^.tt = nsubrange then
  249.                 tq := typeof(tq^.tlo);
  250.             if tq = typnods[tstring] then
  251.                 typeletter := 's'
  252.             else if tq = typnods[tinteger] then
  253.                 typeletter := 'd'
  254.             else if tq = typnods[tchar] then
  255.                 typeletter := 'c'
  256.             else if tq = typnods[treal] then
  257.                 if tp^.tt = nformat then
  258.                     typeletter := 'e'
  259.                 else
  260.                     typeletter := 'g'
  261.             else if tq = typnods[tboolean] then
  262.                 begin
  263.                 typeletter := 'b';
  264.                 nelems := 6
  265.                 end
  266.             else if tq^.tt = narray then
  267.                 begin
  268.                 typeletter := 'a';
  269.                 nelems := crange(tq^.taindx)
  270.                 end
  271.             else if tq^.tt = nconfarr then
  272.                 begin
  273.                 typeletter := 'v';
  274.                 nelems := 0
  275.                 end
  276.             else
  277.                 fatal(etree);
  278.         999:
  279.         end;    (* typeletter *)
  280.  
  281.         procedure etxt(tp : treeptr);
  282.  
  283.         var    w    : toknbuf;
  284.             c    : char;
  285.             i    : toknidx;
  286.  
  287.         begin
  288.             case tp^.tt of
  289.               nid:
  290.                 begin
  291.                 tp := idup(tp);
  292.                 if tp^.tt = nconst then
  293.                     etxt(tp^.tbind)
  294.                 else
  295.                     fatal(etree)
  296.                 end;
  297.               nstring:
  298.                 begin
  299.                 (* printf format string *)
  300.                 gettokn(tp^.tsym^.lstr, w);
  301.                 i := 1;
  302.                 while w[i] <> chr(null) do
  303.                     begin
  304.                     c := w[i];
  305.                     if (c = cite) or (c = bslash) then
  306.                         write(bslash)
  307.                     else if c = percent then
  308.                         write(percent);
  309.                     write(c);
  310.                     i := i + 1
  311.                     end
  312.                 end;
  313.               nchar:
  314.                 begin
  315.                 (* single character in printf format *)
  316.                 c := tp^.tsym^.lchar;
  317.                 if (c = cite) or (c = bslash) then
  318.                     write(bslash)
  319.                 else if c = percent then
  320.                     write(percent);
  321.                 write(c)
  322.                 end;
  323.             end;(* case *)
  324.         end;    (* etxt *)
  325.  
  326.         (*    Emit format for fprintf.            *)
  327.         procedure eformat(tq : treeptr);
  328.  
  329.         var    tx    : treeptr;
  330.             i    : integer;
  331.  
  332.         begin
  333.             case typeletter(tq) of
  334.               'a':
  335.                 begin
  336.                 write(percent);
  337.                 if tq^.tt = nformat then
  338.                     if tq^.texpr^.tt = ninteger then
  339.                         eexpr(tq^.texpr)
  340.                     else
  341.                         write('*');
  342.                 write('.', nelems:1, 's')
  343.                 end;
  344.               'b':
  345.                 begin
  346.                 write(percent);
  347.                 if tq^.tt = nformat then
  348.                     begin
  349.                     if tq^.texpr^.tt = ninteger then
  350.                         eexpr(tq^.texpr)
  351.                     else
  352.                         write('*')
  353.                     end;
  354.                 write('s')
  355.                 end;
  356.               'c':
  357.                 if tq^.tt = nchar then
  358.                     etxt(tq)
  359.                 else begin
  360.                     write(percent);
  361.                     if tq^.tt = nformat then
  362.                         if tq^.texpr^.tt = ninteger then
  363.                             eexpr(tq^.texpr)
  364.                         else
  365.                             write('*');
  366.                     write('c')
  367.                      end;
  368.               'd':
  369.                 begin
  370.                 write(percent);
  371.                 if tq^.tt = nformat then
  372.                     begin
  373.                     if tq^.texpr^.tt = ninteger then
  374.                         eexpr(tq^.texpr)
  375.                     else
  376.                         write('*')
  377.                     end
  378.                 else
  379.                     write(intlen:1);
  380.                 write('d')
  381.                 end;
  382.               'e':
  383.                 begin
  384.                 write(percent, space);
  385.                 tx := tq^.texpr;
  386.                 if tx^.tt = ninteger then
  387.                     begin
  388.                     i := cvalof(tx);
  389.                     write(i:1, '.');
  390.                     i := i - 7;
  391.                     if i < 1 then
  392.                         write('1')
  393.                     else
  394.                         write(i:1)
  395.                     end
  396.                 else
  397.                     write('*.*');
  398.                 write('e')
  399.                 end;
  400.               'f':
  401.                 begin
  402.                 write(percent);
  403.                 tx := tq^.texpl;
  404.                 if tx^.texpr^.tt = ninteger then
  405.                     begin
  406.                     eexpr(tx^.texpr);
  407.                     write('.');
  408.                     tx := tq^.texpr;
  409.                     if tx^.tt = ninteger then
  410.                         begin
  411.                         i := cvalof(tx);
  412.                         tx := tq^.texpl^.texpr;
  413.                         if i > cvalof(tx) - 1 then
  414.                             write('1')
  415.                         else
  416.                             write(i:1)
  417.                         end
  418.                     else
  419.                         write('*');
  420.                     end
  421.                 else
  422.                     write('*.*');
  423.                 write('f')
  424.                 end;
  425.               'g':
  426.                 write(percent, fixlen:1, 'e');
  427.               's':
  428.                 if tq^.tt = nstring then
  429.                     etxt(tq)
  430.                 else begin
  431.                     write(percent);
  432.                     if tq^.tt = nformat then
  433.                         if tq^.texpr^.tt = ninteger then
  434.                             eexpr(tq^.texpr)
  435.                         else
  436.                             write('*.*');
  437.                     write('s')
  438.                      end
  439.             end (* case *)
  440.         end;    (* eformat *)
  441.  
  442.         (*    Emit parameters to fprintf except format.    *)
  443.         procedure ewrite(tq : treeptr);
  444.  
  445.         var    tx    : treeptr;
  446.  
  447.         begin
  448.             case typeletter(tq) of
  449.               'a':
  450.                 begin
  451.                 write(', ');
  452.                 tx := tq;
  453.                 if tq^.tt = nformat then
  454.                     begin
  455.                     if tq^.texpr^.tt <> ninteger then
  456.                         begin
  457.                           eexpr(tq^.texpr);
  458.                           write(', ')
  459.                         end;
  460.                     tx := tq^.texpl
  461.                     end;
  462.                 eexpr(tx);
  463.                 write('.A')
  464.                 end;
  465.               'b':
  466.                 begin
  467.                 write(', ');
  468.                 tx := tq;
  469.                 if tq^.tt = nformat then
  470.                     begin
  471.                     if tq^.texpr^.tt <> ninteger then
  472.                         begin
  473.                           eexpr(tq^.texpr);
  474.                           write(', ')
  475.                         end;
  476.                     tx := tq^.texpl
  477.                     end;
  478.                 usebool := true;
  479.                 write('Bools[(int)(');
  480.                 eexpr(tx);
  481.                 write(')]')
  482.                 end;
  483.               'c':
  484.                 begin
  485.                 if tq^.tt = nformat then
  486.                     begin
  487.                     if tq^.texpr^.tt <> ninteger then
  488.                         begin
  489.                         write(', ');
  490.                         eexpr(tq^.texpr)
  491.                         end;
  492.                     write(', ');
  493.                     eexpr(tq^.texpl)
  494.                     end
  495.                 else if tq^.tt <> nchar then
  496.                     begin
  497.                     write(', ');
  498.                     eexpr(tq)
  499.                     end
  500.                 end;
  501.               'd':
  502.                 begin
  503.                 write(', ');
  504.                 tx := tq;
  505.                 if tq^.tt = nformat then
  506.                     begin
  507.                     if tq^.texpr^.tt <> ninteger then
  508.                         begin
  509.                         eexpr(tq^.texpr);
  510.                         write(', ')
  511.                         end;
  512.                     tx := tq^.texpl
  513.                     end;
  514.                 eexpr(tx)
  515.                 end;
  516.               'e':
  517.                 begin
  518.                 write(', ');
  519.                 tx := tq^.texpr;
  520.                 if tx^.tt <> ninteger then
  521.                     begin
  522.                     usemax := true;
  523.                     eexpr(tx);
  524.                     write(', Max(');
  525.                     eexpr(tx);
  526.                     write(' - 7, 1), ')
  527.                     end;
  528.                 eexpr(tq^.texpl)
  529.                 end;
  530.               'f':
  531.                 begin
  532.                 write(', ');
  533.                 tx := tq^.texpl;
  534.                 if tx^.texpr^.tt <> ninteger then
  535.                     begin
  536.                     eexpr(tx^.texpr);
  537.                     write(', ')
  538.                     end;
  539.                 if (tx^.texpr^.tt <> ninteger) or
  540.                     (tq^.texpr^.tt <> ninteger) then
  541.                     begin
  542.                     usemax := true;
  543.                     write('Max((');
  544.                     eexpr(tx^.texpr);
  545.                     write(') - (');
  546.                     eexpr(tq^.texpr);
  547.                     write(') - 1, 1), ')
  548.                     end;
  549.                 eexpr(tq^.texpl^.texpl)
  550.                 end;
  551.               'g':
  552.                 begin
  553.                 write(', ');
  554.                 eexpr(tq)
  555.                 end;
  556.               's':
  557.                 begin
  558.                 if tq^.tt = nformat then
  559.                     begin
  560.                     if tq^.texpr^.tt <> ninteger then
  561.                        begin
  562.                         write(', ');
  563.                         eexpr(tq^.texpr);
  564.                         write(', ');
  565.                         eexpr(tq^.texpr)
  566.                        end;
  567.                     write(', ');
  568.                     eexpr(tq^.texpl)
  569.                     end
  570.                 else if tq^.tt <> nstring then
  571.                     begin
  572.                     write(', ');
  573.                     eexpr(tq)
  574.                     end
  575.                 end
  576.             end (* case *)
  577.         end;    (* ewrite *)
  578.  
  579.         (*    Emit size of *tp for call to malloc. CPU    *)
  580.         (*    There is no safe way to compute the size of a    *)
  581.         (*    particular variant of a C-union, we assume that    *)
  582.         (*    the size can be computed by taking the address    *)
  583.         (*    of the first member and subracting the address    *)
  584.         (*    of the record and then adding the size of the    *)
  585.         (*    variant containing the record.            *)
  586.         procedure enewsize(tp : treeptr);
  587.  
  588.         label    555;
  589.  
  590.         var    tq, tx, ty    : treeptr;
  591.             v        : integer;
  592.  
  593.             (*    Emit size of union member tq.        *)
  594.             procedure esubsize(tp, tq : treeptr);
  595.  
  596.             label    555, 666;
  597.  
  598.             var    tx, ty    : treeptr;
  599.                 addsize    : boolean;
  600.  
  601.             begin
  602.                 tx := tq^.tvrnt;
  603.                 ty := tx^.tflist;
  604.                 if ty = nil then
  605.                     begin
  606.                     ty := tx^.tvlist;
  607.                     while ty <> nil do
  608.                         begin
  609.                         if ty^.tvrnt^.tflist <> nil then
  610.                             begin
  611.                             ty := ty^.tvrnt^.tflist;
  612.                             goto 555
  613.                             end;
  614.                         ty := ty^.tnext
  615.                         end;
  616.                 555:
  617.                     end;
  618.                 addsize := true;
  619.                 if ty = nil then
  620.                     begin
  621.                     (* empty variant, try using another *)
  622.                     addsize := false;
  623.                     ty := tx^.tup^.tup^.tvlist;
  624.                     while ty <> nil do
  625.                         begin
  626.                         if ty^.tvrnt^.tflist <> nil then
  627.                             begin
  628.                             ty := ty^.tvrnt^.tflist;
  629.                             goto 666
  630.                             end;
  631.                         ty := ty^.tnext
  632.                         end;
  633.                 666:
  634.                     end;
  635.                 if ty = nil then
  636.                     begin
  637.                     (* its getting too complicated,
  638.                         ignore tag value *)
  639.                     write('sizeof(*');
  640.                     eexpr(tp);
  641.                     write(')')
  642.                     end
  643.                 else begin
  644.                     (* compute offset to first member of
  645.                        the selected union variant *)
  646.                     write('Unionoffs(');
  647.                     eexpr(tp);
  648.                     write(', ');
  649.                     printid(ty^.tidl^.tsym^.lid);
  650.                     if addsize then
  651.                         begin
  652.                         (* add the size of the selected
  653.                            union variant *)
  654.                         write(') + sizeof(');
  655.                         eexpr(tp);
  656.                         write('->');
  657.                         printid(tx^.tuid)
  658.                         end;
  659.                     write(')')
  660.                      end
  661.             end;
  662.  
  663.         begin    (* newsize *)
  664.             if (tp^.tnext <> nil) and unionnew then
  665.                 begin
  666.                 (* tnext points to a tag-value, evaluate it *)
  667.                 v := cvalof(tp^.tnext);
  668.                 (* find union type *)
  669.                 tq := typeof(tp);
  670.                 tq := typeof(tq^.tptrid);
  671.                 if tq^.tt <> nrecord then
  672.                     fatal(etree);
  673.                 (* find corresponding variant *)
  674.                 tx := tq^.tvlist;
  675.                 while tx <> nil do
  676.                     begin
  677.                     ty := tx^.tselct;
  678.                     while ty <> nil do
  679.                         begin
  680.                         if v = cvalof(ty) then
  681.                             goto 555;
  682.                         ty := ty^.tnext
  683.                         end;
  684.                     tx := tx^.tnext
  685.                     end;
  686.                 fatal(etag);
  687.             555:
  688.                 (* emit size for that variant *)
  689.                 esubsize(tp, tx)
  690.                 end
  691.             else begin
  692.                 write('sizeof(*');
  693.                 eexpr(tp);
  694.                 write(')')
  695.                  end
  696.         end;    (* newsize *)
  697.  
  698.     begin    (* epredef *)
  699.         td := ts^.tsubstmt^.tdef;
  700.         case td of
  701.           dabs:
  702.             begin
  703.             tq := typeof(tp^.taparm);
  704.             if (tq = typnods[tinteger]) or (tq^.tt = nsubrange) then
  705.                 write('abs(')            (* LIB *)
  706.             else
  707.                 write('fabs(');            (* LIB *)
  708.             eexpr(tp^.taparm);
  709.             write(')')
  710.             end;
  711.           dargv:
  712.             begin
  713.             write('Argvgt(');
  714.             eexpr(tp^.taparm);
  715.             write(', ');
  716.             eexpr(tp^.taparm^.tnext);
  717.             write('.A, sizeof(');
  718.             eexpr(tp^.taparm^.tnext);
  719.             writeln('.A));')
  720.             end;
  721.           dchr:
  722.             begin
  723.             tq := typeof(tp^.taparm);
  724.             if tq^.tt = nsubrange then
  725.                 if tq^.tup^.tt = nconfarr then
  726.                     tq := typeof(tq^.tup^.tindtyp)
  727.                 else
  728.                     tq := typeof(tq^.tlo);
  729.             if (tq = typnods[tinteger]) or
  730.                         (tq = typnods[tchar]) then
  731.                 eexpr(tp^.taparm)
  732.             else begin
  733.                 write('(char)(');
  734.                 eexpr(tp^.taparm);
  735.                 write(')')
  736.                  end
  737.             end;
  738.           ddispose:
  739.             begin
  740.             write('free(');                (* LIB *)
  741.             eexpr(tp^.taparm);
  742.             writeln(');')
  743.             end;
  744.           deof:
  745.             begin
  746.             write('Eof(');
  747.             if tp^.taparm = nil then
  748.                 begin
  749.                 defnams[dinput]^.lused := true;
  750.                 printid(defnams[dinput]^.lid)
  751.                 end
  752.             else
  753.                 eexpr(tp^.taparm);
  754.             write(')')
  755.             end;
  756.           deoln:
  757.             begin
  758.             write('Eoln(');
  759.             if tp^.taparm = nil then
  760.                 begin
  761.                 defnams[dinput]^.lused := true;
  762.                 printid(defnams[dinput]^.lid)
  763.                 end
  764.             else
  765.                 eexpr(tp^.taparm);
  766.             write(')');
  767.             end;
  768.           dexit:
  769.             begin
  770.             write('exit(');                (* OS *)
  771.             if tp^.taparm = nil then
  772.                 write('0')
  773.             else
  774.                 eexpr(tp^.taparm);
  775.             writeln(');');
  776.             end;
  777.           dflush:
  778.             begin
  779.             write('fflush(');            (* LIB *)
  780.             if tp^.taparm = nil then
  781.                 begin
  782.                 defnams[doutput]^.lused := true;
  783.                 printid(defnams[doutput]^.lid)
  784.                 end
  785.             else
  786.                 eexpr(tp^.taparm);
  787.             writeln('.fp);')
  788.             end;
  789.           dpage:
  790.             begin
  791.             (* write form-feed character *)
  792.             write('Putchr(', ffchr, ', '); (* CHAR *)
  793.             if tp^.taparm = nil then
  794.                 begin
  795.                 defnams[doutput]^.lused := true;
  796.                 printid(defnams[doutput]^.lid)
  797.                 end
  798.             else
  799.                 eexpr(tp^.taparm);
  800.             writeln(');');
  801.             end;
  802.           dput,
  803.           dget:
  804.             begin
  805.             if typeof(tp^.taparm) = typnods[ttext] then
  806.                 if td = dget then
  807.                     write('Getx')
  808.                 else
  809.                     write('Putx')
  810.             else begin
  811.                 write(voidcast);
  812.                 if td = dget then
  813.                     write('Get')
  814.                 else
  815.                     write('Put')
  816.                  end;
  817.             write('(');
  818.             eexpr(tp^.taparm);
  819.             writeln(');')
  820.             end;
  821.           dhalt:
  822.             writeln('abort();');            (* OS *)
  823.           dnew:
  824.             begin
  825.             eexpr(tp^.taparm);
  826.             write(' = (');
  827.             etypedef(typeof(tp^.taparm));
  828.             write(')malloc((unsigned)(');    (* LIB *)
  829.             enewsize(tp^.taparm);
  830.             writeln('));')
  831.             end;
  832.           dord:
  833.             begin
  834.             write('(unsigned)(');
  835.             eexpr(tp^.taparm);
  836.             write(')')
  837.             end;
  838.           dread,
  839.           dreadln:
  840.             begin
  841.             txtfile := false;
  842.             tq := tp^.taparm;
  843.             if tq <> nil then
  844.                 begin
  845.                 tv := typeof(tq);
  846.                 if tv = typnods[ttext] then
  847.                     begin
  848.                     (* reading from textfile *)
  849.                     txtfile := true;
  850.                     tv := tq;
  851.                     tq := tq^.tnext
  852.                     end
  853.                 else if tv^.tt = nfileof then
  854.                     begin
  855.                     (* reading from other file *)
  856.                     txtfile := typeof(tv^.tof) =
  857.                             typnods[tchar];
  858.                     tv := tq;
  859.                     tq := tq^.tnext
  860.                     end
  861.                 else begin
  862.                     (* reading from std-input *)
  863.                     txtfile := true;
  864.                     tv := nil
  865.                      end
  866.                 end
  867.             else begin
  868.                 tv := nil;
  869.                 txtfile := true
  870.                  end;
  871.             if txtfile then
  872.                 begin
  873.                 (* check for special case *)
  874.                 if tq = nil then
  875.                     goto 444;
  876.                 if (tq^.tt <> nformat) and
  877.                         (tq^.tnext = nil) and
  878.                         (typeletter(tq) = 'c') then
  879.                     begin
  880.                     (* read single char *)
  881.                     eexpr(tq);
  882.                     write(' = ');
  883.                     write('Getchr(');
  884.                     if tv = nil then
  885.                         printid(defnams[dinput]^.lid)
  886.                     else
  887.                         eexpr(tv);
  888.                     write(')');
  889.                     if td = dreadln then
  890.                         write(',');
  891.                     goto 444
  892.                     end;
  893.                 usescan := true;
  894.                 write('Fscan(');
  895.                 if tv = nil then
  896.                     printid(defnams[dinput]^.lid)
  897.                 else
  898.                     eexpr(tv);
  899.                 write('), ');
  900.                 (* first pass, emit format string *)
  901.                 while tq <> nil do
  902.                     begin
  903.                     write('Scan(', cite);
  904.                     ch := typeletter(tq);
  905.                     case ch of
  906.                       'a':
  907.                         write(percent, 's');
  908.                       'c':
  909.                         write(percent, 'c');
  910.                       'd':
  911.                         write(percent, 'ld');
  912.                       'g':
  913.                         write(percent, 'le')
  914.                     end;(* case *)
  915.                     write(cite, ', ');
  916.                     case ch of
  917.                       'a':
  918.                         begin
  919.                         eexpr(tq);
  920.                         write('.A')
  921.                         end;
  922.                       'c':
  923.                         begin
  924.                         write('&');
  925.                         eexpr(tq)
  926.                         end;
  927.                       'd':
  928.                         write('&Tmplng');
  929.                       'g':
  930.                         write('&Tmpdbl')
  931.                     end;(* case *)
  932.                     write(')');
  933.                     case ch of
  934.                       'd':
  935.                         begin
  936.                         write(', ');
  937.                         eexpr(tq);
  938.                         write(' = Tmplng')
  939.                         end;
  940.                       'g':
  941.                         begin
  942.                         write(', ');
  943.                         eexpr(tq);
  944.                         write(' = Tmpdbl')
  945.                         end;
  946.                       'a',
  947.                       'c':
  948.                         (* no op *)
  949.                     end;(* case *)
  950.                     tq := tq^.tnext;
  951.                     if tq <> nil then
  952.                         begin
  953.                         writeln(',');
  954.                         indent;
  955.                         write(tab1)
  956.                         end
  957.                     end;
  958.                 write(', Getx(');
  959.                 if tv = nil then
  960.                     printid(defnams[dinput]^.lid)
  961.                 else
  962.                     eexpr(tv);
  963.                 write(')');
  964.                 if td = dreadln then
  965.                     write(',');
  966.             444:
  967.                 if td = dreadln then
  968.                     begin
  969.                     usegetl := true;
  970.                     write('Getl(&');
  971.                     if tv = nil then
  972.                         printid(defnams[dinput]^.lid)
  973.                     else
  974.                         eexpr(tv);
  975.                     write(')')
  976.                     end
  977.                 end
  978.             else begin
  979.                 increment;
  980.                 while tq <> nil do
  981.                     begin
  982.                     write(voidcast, 'Fread(');
  983.                     eexpr(tq);
  984.                     write(', ');
  985.                     eexpr(tv);
  986.                     write('.fp)');
  987.                     tq := tq^.tnext;
  988.                     if tq <> nil then
  989.                         begin
  990.                         writeln(',');
  991.                         indent
  992.                         end
  993.                     end;
  994.                 decrement
  995.                  end;
  996.             writeln(';')
  997.             end;
  998.           dwrite,
  999.           dwriteln,
  1000.           dmessage:
  1001.             begin
  1002.             txtfile := false;
  1003.             tq := tp^.taparm;
  1004.             if tq <> nil then
  1005.                 begin
  1006.                 tv := typeof(tq);
  1007.                 if tv = typnods[ttext] then
  1008.                     begin
  1009.                     (* writing to textfile *)
  1010.                     txtfile := true;
  1011.                     tv := tq;
  1012.                     tq := tq^.tnext
  1013.                     end
  1014.                 else if tv^.tt = nfileof then
  1015.                     begin
  1016.                     (* writing to other file *)
  1017.                     txtfile := typeof(tv^.tof) =
  1018.                             typnods[tchar];
  1019.                     tv := tq;
  1020.                     tq := tq^.tnext
  1021.                     end
  1022.                 else begin
  1023.                     (* writing to std-output *)
  1024.                     txtfile := true;
  1025.                     tv := nil
  1026.                      end
  1027.                 end
  1028.             else begin
  1029.                 tv := nil;
  1030.                 txtfile := true
  1031.                  end;
  1032.             if txtfile then
  1033.                 begin
  1034.                 (* check for special case *)
  1035.                 if tq = nil then
  1036.                     begin
  1037.                     (* writeln whithout parameters *)
  1038.                     if td in [dwriteln, dmessage] then
  1039.                         begin
  1040.                         write('Putchr(', nlchr, ', ');
  1041.                         if tv = nil then
  1042.                             printid(
  1043.                               defnams[doutput]^.lid)
  1044.                         else
  1045.                             eexpr(tv);
  1046.                         write(')')
  1047.                         end;
  1048.                     writeln(';');
  1049.                     goto 555
  1050.                     end
  1051.                 else if (tq^.tt <> nformat) and
  1052.                         (tq^.tnext = nil) then
  1053.                     if typeletter(tq) = 'c' then
  1054.                         begin
  1055.                         (* print single char *)
  1056.                         write('Putchr(');
  1057.                         eexpr(tq);
  1058.                         write(', ');
  1059.                         if tv = nil then
  1060.                             printid(
  1061.                               defnams[doutput]^.lid)
  1062.                         else
  1063.                             eexpr(tv);
  1064.                         write(')');
  1065.                         if td = dwriteln then
  1066.                             begin
  1067.                             write(',Putchr(',
  1068.                                 nlchr, ', ');
  1069.                             if tv = nil then
  1070.                              printid(
  1071.                               defnams[doutput]^.lid)
  1072.                             else
  1073.                                 eexpr(tv);
  1074.                             write(')');
  1075.                             end;
  1076.                         writeln(';');
  1077.                         goto 555
  1078.                         end;
  1079.                 tx := nil;
  1080.                 write(voidcast, 'fprintf(');    (* LIB *)
  1081.                 if td = dmessage then
  1082.                     write('stderr, ')
  1083.                 else begin
  1084.                     if tv = nil then
  1085.                         printid(defnams[doutput]^.lid)
  1086.                     else
  1087.                         eexpr(tv);
  1088.                     write('.fp, ')
  1089.                      end;
  1090.                 write(cite);
  1091.                 tx := tq;    (* remember 1:st parm *)
  1092.                 (* first pass, emit format string *)
  1093.                 while tq <> nil do
  1094.                     begin
  1095.                     eformat(tq);
  1096.                     tq := tq^.tnext
  1097.                     end;
  1098.                 if (td = dmessage) or (td = dwriteln) then
  1099.                     write('\n');
  1100.                 write(cite);
  1101.                 (* second pass, add parameters *)
  1102.                 tq := tx;
  1103.                 while tq <> nil do
  1104.                     begin
  1105.                     ewrite(tq);
  1106.                     tq := tq^.tnext
  1107.                     end;
  1108.                 write('), Putl(');
  1109.                 if tv = nil then
  1110.                     printid(defnams[doutput]^.lid)
  1111.                 else
  1112.                     eexpr(tv);
  1113.                 if td = dwrite then
  1114.                     write(', 0)')
  1115.                 else
  1116.                     write(', 1)')
  1117.                 end
  1118.             else begin
  1119.                 increment;
  1120.                 tx := typeof(tv);
  1121.                 if tx = typnods[ttext] then
  1122.                     tx := typnods[tchar]
  1123.                 else if tx^.tt = nfileof then
  1124.                     tx := typeof(tx^.tof)
  1125.                 else
  1126.                     fatal(etree);
  1127.                 while tq <> nil do
  1128.                     begin
  1129.                     if (tq^.tt in [nid, nindex, nselect,
  1130.                             nderef]) and
  1131.                         (tx = typeof(tq)) then
  1132.                         begin
  1133.                         write(voidcast, 'Fwrite(');
  1134.                         eexpr(tq)
  1135.                         end
  1136.                     else begin
  1137.                         if tx^.tt = nsetof then
  1138.                             begin
  1139.                             usescpy := true;
  1140.                             write('Setncpy(');
  1141.                             eselect(tv);
  1142.                             write('buf.S, ');
  1143.                             eexpr(tq);
  1144.                             if typeof(tp^.trhs) =
  1145.                                typnods[tset] then
  1146.                                 eexpr(tq)
  1147.                             else begin
  1148.                                 eselect(tq);
  1149.                                 write('S')
  1150.                                  end;
  1151.                             write(', sizeof(');
  1152.                             eexpr(tv);
  1153.                             write('.buf))');
  1154.                             end
  1155.                         else begin
  1156.                             eexpr(tv);
  1157.                             write('.buf = ');
  1158.                             eexpr(tq)
  1159.                              end;
  1160.                         write(', Fwrite(');
  1161.                         eexpr(tv);
  1162.                         write('.buf');
  1163.                          end;
  1164.                     write(', ');
  1165.                     eexpr(tv);
  1166.                     write('.fp)');
  1167.                     tq := tq^.tnext;
  1168.                     if tq <> nil then
  1169.                         begin
  1170.                         writeln(',');
  1171.                         indent
  1172.                         end
  1173.                     end;
  1174.                 decrement
  1175.                  end;
  1176.             writeln(';');
  1177.         555:
  1178.             end;
  1179.           dclose:
  1180.             begin
  1181.             tq := typeof(tp^.taparm);
  1182.             txtfile := tq = typnods[ttext];
  1183.             if (not txtfile) and (tq^.tt = nfileof) then
  1184.                 if typeof(tq^.tof) = typnods[tchar] then
  1185.                     txtfile := true;
  1186.             if txtfile then
  1187.                 write('Closex(')
  1188.             else
  1189.                 write('Close(');
  1190.             eexpr(tp^.taparm);
  1191.             writeln(');');
  1192.             end;
  1193.           dreset,
  1194.           drewrite:
  1195.             begin
  1196.             tq := typeof(tp^.taparm);
  1197.             txtfile := tq = typnods[ttext];
  1198.             if (not txtfile) and (tq^.tt = nfileof) then
  1199.                 if typeof(tq^.tof) = typnods[tchar] then
  1200.                     txtfile := true;
  1201.             if txtfile then
  1202.                 if td = dreset then
  1203.                     write('Resetx(')
  1204.                 else
  1205.                     write('Rewritex(')
  1206.             else
  1207.                 if td = dreset then
  1208.                     write('Reset(')
  1209.                 else
  1210.                     write('Rewrite(');
  1211.             eexpr(tp^.taparm);
  1212.             write(', ');
  1213.             tq := tp^.taparm^.tnext;
  1214.             if tq = nil then
  1215.                 write('NULL')
  1216.             else begin
  1217.                 tq := typeof(tq);
  1218.                 if tq = typnods[tchar] then
  1219.                     begin
  1220.                     write(cite);
  1221.                     ch := chr(cvalof(tp^.taparm^.tnext));
  1222.                     if (ch = bslash) or (ch = cite) then
  1223.                         write(bslash);
  1224.                     write(ch, cite)
  1225.                     end
  1226.                 else if tq = typnods[tstring] then
  1227.                     eexpr(tp^.taparm^.tnext)
  1228.                 else  if tq^.tt in [narray, nconfarr] then
  1229.                      begin
  1230.                     eexpr(tp^.taparm^.tnext);
  1231.                     write('.A')
  1232.                      end
  1233.                 else
  1234.                     fatal(etree)
  1235.                  end;
  1236.             writeln(');')
  1237.             end;
  1238.           darctan:
  1239.             begin
  1240.             write('atan(');    (* LIB *)
  1241.             if typeof(tp^.taparm) <> typnods[treal] then
  1242.                 write(dblcast);
  1243.             eexpr(tp^.taparm);
  1244.             write(')')
  1245.             end;
  1246.           dln:
  1247.             begin
  1248.             write('log(');    (* LIB *)
  1249.             if typeof(tp^.taparm) <> typnods[treal] then
  1250.                 write(dblcast);
  1251.             eexpr(tp^.taparm);
  1252.             write(')')
  1253.             end;
  1254.           dexp:
  1255.             begin
  1256.             write('exp(');    (* LIB *)
  1257.             if typeof(tp^.taparm) <> typnods[treal] then
  1258.                 write(dblcast);
  1259.             eexpr(tp^.taparm);
  1260.             write(')')
  1261.             end;
  1262.           dcos,
  1263.           dsin,
  1264.           dsqrt:
  1265.             begin
  1266.             eexpr(tp^.tcall);    (* LIB *)
  1267.             write('(');
  1268.             if typeof(tp^.taparm) <> typnods[treal] then
  1269.                 write(dblcast);
  1270.             eexpr(tp^.taparm);
  1271.             write(')')
  1272.             end;
  1273.           dtan:
  1274.             begin
  1275.             write('atan(');        (* LIB *)
  1276.             if typeof(tp^.taparm) <> typnods[treal] then
  1277.                 write(dblcast);
  1278.             eexpr(tp^.taparm);
  1279.             write(')')
  1280.             end;
  1281.           dsucc,
  1282.           dpred:
  1283.             begin
  1284.             tq := typeof(tp^.taparm);
  1285.             if tq^.tt = nsubrange then
  1286.                 if tq^.tup^.tt = nconfarr then
  1287.                     tq := typeof(tq^.tup^.tindtyp)
  1288.                 else
  1289.                     tq := typeof(tq^.tlo);
  1290.             if (tq = typnods[tinteger]) or
  1291.                         (tq = typnods[tchar]) then
  1292.                 begin
  1293.                 write('((');
  1294.                 eexpr(tp^.taparm);
  1295.                 if td = dpred then
  1296.                     write(')-1)')
  1297.                 else
  1298.                     write(')+1)')
  1299.                 end
  1300.             else begin
  1301.                 (* some sort of scalar type, casting needed *)
  1302.                 write('(');
  1303.                 tq := tq^.tup;
  1304.                 if tq^.tt = ntype then
  1305.                     begin
  1306.                     (* cast only if it is a named type *)
  1307.                     write('(');
  1308.                     printid(tq^.tidl^.tsym^.lid);
  1309.                     write(')')
  1310.                     end;
  1311.                 write('((int)(');
  1312.                 eexpr(tp^.taparm);
  1313.                 if td = dpred then
  1314.                     write(')-1))')
  1315.                 else
  1316.                     write(')+1))')
  1317.                  end
  1318.             end;
  1319.           dodd:
  1320.             begin
  1321.             write('(');
  1322.             printid(defnams[dboolean]^.lid);
  1323.             write(')((');
  1324.             eexpr(tp^.taparm);
  1325.             write(') & 1)')
  1326.             end;
  1327.           dsqr:
  1328.             begin
  1329.             tq := typeof(tp^.taparm);
  1330.             if (tq = typnods[tinteger]) or (tq^.tt = nsubrange) then
  1331.                 begin
  1332.                 write('((');
  1333.                 eexpr(tp^.taparm);
  1334.                 write(') * (');
  1335.                 eexpr(tp^.taparm);
  1336.                 write('))')
  1337.                 end
  1338.             else begin
  1339.                 write('pow(');    (* LIB *)
  1340.                 if typeof(tp^.taparm) <> typnods[treal] then
  1341.                     write(dblcast);
  1342.                 eexpr(tp^.taparm);
  1343.                 write(', 2.0)')
  1344.                  end
  1345.             end;
  1346.           dround:
  1347.             begin
  1348.             write('Round(');
  1349.             eexpr(tp^.taparm);
  1350.             write(')')
  1351.             end;
  1352.           dtrunc:
  1353.             begin
  1354.             write('Trunc(');
  1355.             eexpr(tp^.taparm);
  1356.             write(')')
  1357.             end;
  1358.           dpack:
  1359.             begin
  1360.             tq := typeof(tp^.taparm);
  1361.             tx := typeof(tp^.taparm^.tnext^.tnext);
  1362.             write('{    ', registr, inttyp, tab1, '_j, _i = ');
  1363.             if not arithexpr(tp^.taparm^.tnext) then
  1364.                 write('(int)');
  1365.             eexpr(tp^.taparm^.tnext);
  1366.             if tx^.tt = narray then
  1367.                 write(' - ', clower(tq^.taindx):1);
  1368.             writeln(';');
  1369.             indent;
  1370.             write('    for (_j = 0; _j < ');
  1371.             if tq^.tt = nconfarr then
  1372.                 begin
  1373.                 write('(int)(');
  1374.                 printid(tx^.tcindx^.thi^.tsym^.lid);
  1375.                 write(')')
  1376.                 end
  1377.             else
  1378.                 write(crange(tx^.taindx):1);
  1379.             writeln('; )');
  1380.             indent;
  1381.             write(tab1);
  1382.             eexpr(tp^.taparm^.tnext^.tnext);
  1383.             write('.A[_j++] = ');
  1384.             eexpr(tp^.taparm);
  1385.             writeln('.A[_i++];');
  1386.             indent;
  1387.             writeln('}')
  1388.             end;
  1389.           dunpack:
  1390.             begin
  1391.             tq := typeof(tp^.taparm);
  1392.             tx := typeof(tp^.taparm^.tnext);
  1393.             write('{   ', registr, inttyp, tab1, '_j, _i = ');
  1394.             if not arithexpr(tp^.taparm^.tnext^.tnext) then
  1395.                 write('(int)');
  1396.             eexpr(tp^.taparm^.tnext^.tnext);
  1397.             if tx^.tt <> nconfarr then
  1398.                 write(' - ', clower(tx^.taindx):1);
  1399.             writeln(';');
  1400.             indent;
  1401.             write('    for (_j = 0; _j < ');
  1402.             if tq^.tt = nconfarr then
  1403.                 begin
  1404.                 write('(int)(');
  1405.                 printid(tq^.tcindx^.thi^.tsym^.lid);
  1406.                 write(')')
  1407.                 end
  1408.             else
  1409.                 write(crange(tq^.taindx):1);
  1410.             writeln('; )');
  1411.             indent;
  1412.             write(tab1);
  1413.             eexpr(tp^.taparm^.tnext);
  1414.             write('.A[_i++] = ');
  1415.             eexpr(tp^.taparm);
  1416.             writeln('.A[_j++];');
  1417.             indent;
  1418.             writeln('}')
  1419.             end;
  1420.         end (* case *)
  1421.     end;    (* epredef *)
  1422.  
  1423.     procedure eaddr(tp : treeptr);
  1424.  
  1425.     begin
  1426.         write('&');
  1427.         if not(tp^.tt in [nid, nselect, nindex, nderef]) then
  1428.             error(evarpar);
  1429.         eexpr(tp)
  1430.     end;
  1431.  
  1432.     (*    Emit code for a subroutine call.            *)
  1433.     procedure ecall(tp : treeptr);
  1434.  
  1435.     var    tf, tq, tx    : treeptr;
  1436.  
  1437.     begin
  1438.         (* find first formal parameter id *)
  1439.         tf := idup(tp^.tcall);
  1440.         case tf^.tt of
  1441.           nproc,
  1442.           nfunc:
  1443.             tf := tf^.tsubpar;
  1444.           nparproc,
  1445.           nparfunc:
  1446.             tf := tf^.tparparm
  1447.         end;(* case *)
  1448.         if tf <> nil then
  1449.             begin
  1450.             case tf^.tt of
  1451.               nvalpar,
  1452.               nvarpar:
  1453.                 tf := tf^.tidl;
  1454.               nparproc,
  1455.               nparfunc:
  1456.                 tf := tf^.tparid
  1457.             end (* case *)
  1458.             end;
  1459.         (* emit called function name *)
  1460.         eexpr(tp^.tcall);
  1461.         write('(');
  1462.         (* emit actual parameters *)
  1463.         tq := tp^.taparm;
  1464.         while tq <> nil do
  1465.             begin
  1466.             if tf^.tup^.tt in [nparfunc, nparproc] then
  1467.                 begin
  1468.                 (* single subroutine-nid converted to ncall *)
  1469.                 if tq^.tt = ncall then
  1470.                     printid(tq^.tcall^.tsym^.lid)
  1471.                 else
  1472.                     printid(tq^.tsym^.lid)
  1473.                 end
  1474.             else begin
  1475.                 tx := typeof(tq);
  1476.                 if tx = typnods[tboolean] then
  1477.                     begin
  1478.                     tx := tq;
  1479.                     while tx^.tt = nuplus do
  1480.                         tx := tx^.texps;
  1481.                     if tx^.tt in [nin .. nor, nand, nnot]
  1482.                                     then
  1483.                         begin
  1484.                         write('(');
  1485.                         printid(defnams[dboolean]^.lid);
  1486.                         write(')(');
  1487.                         eexpr(tq);
  1488.                         write(')')
  1489.                         end
  1490.                     else
  1491.                         eexpr(tq);
  1492.                     end
  1493.                 else if (tx = typnods[tstring]) or
  1494.                         (tx = typnods[tset]) then
  1495.                     begin
  1496.                     (* cast literal to proper type *)
  1497.                     write('*((');
  1498.                     etypedef(tf^.tup^.tbind);
  1499.                     write(' *)');
  1500.                     if tx = typnods[tset] then
  1501.                         begin
  1502.                         dropset := true;
  1503.                         eexpr(tq);
  1504.                         dropset := false
  1505.                         end
  1506.                     else
  1507.                         eexpr(tq);
  1508.                     write(')')
  1509.                     end
  1510.                 else if tx = typnods[tnil] then
  1511.                     begin
  1512.                     write('(');
  1513.                     etypedef(tf^.tup^.tbind);
  1514.                     write(')NIL')
  1515.                     end
  1516.                 else if tf^.tup^.tbind^.tt = nconfarr then
  1517.                     begin
  1518.                     write('(struct ');
  1519.                     printid(tf^.tup^.tbind^.tcuid);
  1520.                     write(' *)&');
  1521.                     eexpr(tq);
  1522.                     (* add upper bound of actual value *)
  1523.                     if tq^.tnext = nil then
  1524.                         write(', ',
  1525.                             crange(tx^.taindx):1)
  1526.                     end
  1527.                 else begin
  1528.                     if tf^.tup^.tt = nvarpar then
  1529.                         eaddr(tq)
  1530.                     else
  1531.                         eexpr(tq)
  1532.                      end
  1533.                 end;
  1534.             tq := tq^.tnext;
  1535.             if tq <> nil then
  1536.                 begin
  1537.                 write(', ');
  1538.                 (* next formal parameter *)
  1539.                 if tf^.tnext = nil then
  1540.                     begin
  1541.                     tf := tf^.tup^.tnext;
  1542.                     case tf^.tt of
  1543.                       nvalpar,
  1544.                       nvarpar:
  1545.                         tf := tf^.tidl;
  1546.                       nparproc,
  1547.                       nparfunc:
  1548.                         tf := tf^.tparid
  1549.                     end (* case *)
  1550.                     end
  1551.                 else
  1552.                     tf := tf^.tnext;
  1553.                 end;
  1554.             end;
  1555.         write(')')
  1556.     end;    (* ecall *)
  1557.  
  1558.     (*    Emit code for a general expression.            *)
  1559.     procedure eexpr;
  1560.  
  1561.     label    999;
  1562.  
  1563.     var    tq    : treeptr;
  1564.         flag    : boolean;
  1565.  
  1566.         function constset(tp : treeptr) : boolean;
  1567.  
  1568.             function constxps(tp : treeptr) : boolean;
  1569.             begin
  1570.                 case tp^.tt of
  1571.                   nrange:
  1572.                     if constxps(tp^.texpr) then
  1573.                         constxps := constxps(tp^.texpl)
  1574.                     else
  1575.                         constxps := false;
  1576.                   nempty,
  1577.                   ninteger,
  1578.                   nchar:
  1579.                     constxps := true;
  1580.                   nid:
  1581.                     begin
  1582.                     tp := idup(tp);
  1583.                     constxps := (tp^.tt = nconst)
  1584.                             or (tp^.tt = nscalar)
  1585.                     end;
  1586.                   nin, neq, nne, nlt, nle, ngt, nge, nor,
  1587.                   nplus, nminus, nand, nmul, ndiv, nmod,
  1588.                   nquot, nnot, numinus, nuplus, nset,    
  1589.                   nindex, nselect, nderef, ncall,
  1590.                   nreal, nstring, nnil:
  1591.                     constxps := false
  1592.                 end (* case *)
  1593.             end;
  1594.  
  1595.         begin
  1596.             constset := true;
  1597.             while tp <> nil do
  1598.                 if constxps(tp) then
  1599.                     tp := tp^.tnext
  1600.                 else begin
  1601.                     constset := false;
  1602.                     tp := nil
  1603.                     end
  1604.         end;
  1605.  
  1606.     begin    (* eexpr *)
  1607.         donearr := false;
  1608.         if tp^.tt in [nplus, nminus, nmul, nle, nge, neq, nne] then
  1609.             begin
  1610.             tq := typeof(tp^.texpl);
  1611.             if (tq^.tt in [nset, nsetof]) or
  1612.                         (tq = typnods[tset]) then
  1613.                 begin
  1614.                 (* set operations *)
  1615.                 case tp^.tt of
  1616.                   nplus:
  1617.                     begin
  1618.                     setused := true;
  1619.                     useunion := true;
  1620.                     write('Union')
  1621.                     end;
  1622.                   nminus:
  1623.                     begin
  1624.                     setused := true;
  1625.                     usediff := true;
  1626.                     write('Diff')
  1627.                     end;
  1628.                   nmul:
  1629.                     begin
  1630.                     setused := true;
  1631.                     useintr := true;
  1632.                     write('Inter')
  1633.                     end;
  1634.                   neq:
  1635.                     begin
  1636.                     useseq := true;
  1637.                     write('Eq')
  1638.                     end;
  1639.                   nne:
  1640.                     begin
  1641.                     usesne := true;
  1642.                     write('Ne')
  1643.                     end;
  1644.                   nge:
  1645.                     begin
  1646.                     usesge := true;
  1647.                     write('Ge')
  1648.                     end;
  1649.                   nle:
  1650.                     begin
  1651.                     usesle := true;
  1652.                     write('Le')
  1653.                     end
  1654.                 end;(* case *)
  1655.                 if tp^.tt in [nplus, nminus, nmul] then
  1656.                     dropset := false;
  1657.                 write('(');
  1658.                 eexpr(tp^.texpl);
  1659.                 if tq^.tt = nsetof then
  1660.                     write('.S');
  1661.                 write(', ');
  1662.                 eexpr(tp^.texpr);
  1663.                 tq := typeof(tp^.texpr);
  1664.                 if tq^.tt = nsetof then
  1665.                     write('.S');
  1666.                 write(')');
  1667.                 goto 999
  1668.                 end
  1669.             end;
  1670.         if tp^.tt in [neq, nne, ngt, nlt, nge, nle] then
  1671.             begin
  1672.             tq := typeof(tp^.texpl);
  1673.             if tq^.tt = nconfarr then
  1674.                 fatal(ecmpconf);
  1675.             if (tq^.tt in [nstring, narray]) or
  1676.                         (tq = typnods[tstring]) then
  1677.                 begin
  1678.                 write('Cmpstr(');
  1679.                 eexpr(tp^.texpl);
  1680.                 if tq^.tt = narray then
  1681.                     write('.A');
  1682.                 write(', ');
  1683.                 tq := typeof(tp^.texpr);
  1684.                 if tq^.tt = nconfarr then
  1685.                     fatal(ecmpconf);
  1686.                 eexpr(tp^.texpr);
  1687.                 if tq^.tt = narray then
  1688.                     write('.A');
  1689.                 write(')');
  1690.                 case tp^.tt of
  1691.                   neq:
  1692.                     write(' == ');
  1693.                   nne:
  1694.                     write(' != ');
  1695.                   ngt:
  1696.                     write(' > ');
  1697.                   nlt:
  1698.                     write(' < ');
  1699.                   nge:
  1700.                     write(' >= ');
  1701.                   nle:
  1702.                     write(' <= ');
  1703.                 end;(* case *)
  1704.                 write('0');
  1705.                 goto 999
  1706.                 end
  1707.             end;
  1708.         case tp^.tt of
  1709.           neq, nne, nlt, nle,
  1710.           ngt, nge, nor, nand, nplus, nminus,
  1711.           nmul, ndiv, nmod, nquot:
  1712.             begin
  1713.             flag := cprio[tp^.tt] > cprio[tp^.texpl^.tt];
  1714.             if (tp^.tt in [nlt, nle, ngt, nge]) and
  1715.                     not arithexpr(tp^.texpl) then
  1716.                 begin
  1717.                 write('(int)');
  1718.                 flag := true
  1719.                 end;
  1720.             if flag then
  1721.                 write('(');
  1722.             eexpr(tp^.texpl);
  1723.             if flag then
  1724.                 write(')');
  1725.             case tp^.tt of
  1726.               neq:
  1727.                 write(' == ');
  1728.               nne:
  1729.                 write(' != ');
  1730.               nlt:
  1731.                 write(' < ');
  1732.               nle:
  1733.                 write(' <= ');
  1734.               ngt:
  1735.                 write(' > ');
  1736.               nge:
  1737.                 write(' >= ');
  1738.               nor:
  1739.                 write(' || ');
  1740.               nand:
  1741.                 write(' && ');
  1742.               nplus:
  1743.                 write(' + ');
  1744.               nminus:
  1745.                 write(' - ');
  1746.               nmul:
  1747.                 write(' * ');
  1748.               ndiv:
  1749.                 write(' / ');
  1750.               nmod:
  1751.                 write(' % ');
  1752.               nquot:
  1753.                 begin
  1754.                 write(' / ((');
  1755.                 printid(defnams[dreal]^.lid);
  1756.                 write(')')
  1757.                 end
  1758.             end;(* case *)
  1759.             flag := cprio[tp^.tt] > cprio[tp^.texpr^.tt];
  1760.             if (tp^.tt in [nlt, nle, ngt, nge]) and
  1761.                     not arithexpr(tp^.texpr) then
  1762.                 begin
  1763.                 write('(int)');
  1764.                 flag := true
  1765.                 end;
  1766.             if flag then
  1767.                 write('(');
  1768.             eexpr(tp^.texpr);
  1769.             if flag then
  1770.                 write(')');
  1771.             if tp^.tt = nquot then
  1772.                 write(')')
  1773.             end;
  1774.  
  1775.           nuplus, numinus, nnot:
  1776.             begin
  1777.             case tp^.tt of
  1778.               numinus:
  1779.                 write('-');
  1780.               nnot:
  1781.                 write('!');
  1782.               nuplus:
  1783.             end;(* case *)
  1784.             flag := cprio[tp^.tt] >= cprio[tp^.texps^.tt];
  1785.             if flag then
  1786.                 write('(');
  1787.             eexpr(tp^.texps);
  1788.             if flag then
  1789.                 write(')');
  1790.             end;
  1791.           
  1792.           nin:
  1793.             begin
  1794.             usememb := true;
  1795.             write('Member((unsigned)(');
  1796.             eexpr(tp^.texpl);
  1797.             write('), ');
  1798.             dropset := true;    (* no need to save set-expr *)
  1799.             eexpr(tp^.texpr);
  1800.             dropset := false;
  1801.             tq := typeof(tp^.texpr);
  1802.             if tq^.tt = nsetof then
  1803.                 write('.S');
  1804.             write(')')
  1805.             end;
  1806.  
  1807.           nassign:
  1808.             begin
  1809.             tq := typeof(tp^.trhs);
  1810.             if tq = typnods[tstring] then
  1811.                 begin
  1812.                 write(voidcast, 'strncpy(');
  1813.                 eexpr(tp^.tlhs);
  1814.                 write('.A, ');
  1815.                 eexpr(tp^.trhs);
  1816.                 write(', sizeof(');
  1817.                 eexpr(tp^.tlhs);
  1818.                 write('.A))')
  1819.                 end
  1820.             else if tq = typnods[tboolean] then
  1821.                 begin
  1822.                 eexpr(tp^.tlhs);
  1823.                 write(' = ');
  1824.                 tq := tp^.trhs;
  1825.                 while tq^.tt = nuplus do
  1826.                     tq := tq^.texps;
  1827.                 if tq^.tt in [nin .. nor, nand, nnot] then
  1828.                     begin
  1829.                     write('(');
  1830.                     printid(defnams[dboolean]^.lid);
  1831.                     write(')(');
  1832.                     eexpr(tq);
  1833.                     write(')')
  1834.                     end
  1835.                 else
  1836.                     eexpr(tq)
  1837.                 end
  1838.             else if tq = typnods[tnil] then
  1839.                 begin
  1840.                 eexpr(tp^.tlhs);
  1841.                 write(' = (');
  1842.                 etypedef(typeof(tp^.tlhs));
  1843.                 write(')NIL')
  1844.                 end
  1845.             else begin
  1846.                 tq := typeof(tp^.tlhs);
  1847.                 if tq^.tt = nsetof then
  1848.                     begin
  1849.                     usescpy := true;
  1850.                     write('Setncpy(');
  1851.                     eselect(tp^.tlhs);
  1852.                     write('S, ');
  1853.                     dropset := true;
  1854.                     tq := typeof(tp^.trhs);
  1855.                     if tq = typnods[tset] then
  1856.                         eexpr(tp^.trhs)
  1857.                     else begin
  1858.                         eselect(tp^.trhs);
  1859.                         write('S')
  1860.                          end;
  1861.                     dropset := false;
  1862.                     write(', sizeof(');
  1863.                     eselect(tp^.tlhs);
  1864.                     write('S))')
  1865.                     end
  1866.                 else begin
  1867.                     eexpr(tp^.tlhs);
  1868.                     write(' = ');
  1869.                     eexpr(tp^.trhs)
  1870.                      end
  1871.                  end
  1872.             end;
  1873.  
  1874.           ncall:
  1875.             begin
  1876.             tq := idup(tp^.tcall);
  1877.             if (tq^.tt in [nfunc, nproc]) and
  1878.                     (tq^.tsubstmt <> nil) then
  1879.                 if tq^.tsubstmt^.tt = npredef then
  1880.                     epredef(tq, tp)
  1881.                 else
  1882.                     ecall(tp)
  1883.             else
  1884.                 ecall(tp)
  1885.             end;
  1886.  
  1887.           nselect:
  1888.             begin
  1889.             eselect(tp^.trecord);
  1890.             eexpr(tp^.tfield)
  1891.             end;
  1892.           nindex:
  1893.             begin
  1894.             eselect(tp^.tvariable);
  1895.             write('A[');
  1896.             tq := tp^.toffset;
  1897.             if arithexpr(tq) then
  1898.                 eexpr(tq)
  1899.             else begin
  1900.                 write('(int)(');
  1901.                 eexpr(tq);
  1902.                 write(')')
  1903.                  end;
  1904.             tq := typeof(tp^.tvariable);
  1905.             if tq^.tt = narray then
  1906.                 if clower(tq^.taindx) <> 0 then
  1907.                     begin
  1908.                     write(' - ');
  1909.                     tq := typeof(tq^.taindx);
  1910.                     if tq^.tt = nsubrange then
  1911.                         if arithexpr(tq^.tlo) then
  1912.                             eexpr(tq^.tlo)
  1913.                         else begin
  1914.                             write('(int)(');
  1915.                             eexpr(tq^.tlo);
  1916.                             write(')')
  1917.                              end
  1918.                     else 
  1919.                         fatal(etree)
  1920.                     end;
  1921.             write(']')
  1922.             end;
  1923.           nderef:
  1924.             begin
  1925.             tq := typeof(tp^.texps);
  1926.             if (tq^.tt = nfileof) or
  1927.                  ((tq^.tt = npredef) and (tq^.tdef = dtext)) then
  1928.                 begin
  1929.                 (* using a file-variable as pointer *)
  1930.                 eexpr(tp^.texps);
  1931.                 write('.buf')
  1932.                 end
  1933.             else if doarrow = 0 then
  1934.                 begin
  1935.                 write('*');
  1936.                 eexpr(tp^.texps)
  1937.                 end
  1938.             else begin
  1939.                 eexpr(tp^.texps);
  1940.                 write('->');
  1941.                 donearr := true
  1942.                  end
  1943.             end;
  1944.           nid:
  1945.             begin
  1946.             (* add pointer-dereference if this id is declared as a
  1947.                var-parameter or as a procedure-parameter *)
  1948.             tq := idup(tp);
  1949.             if tq^.tt = nvarpar then
  1950.                 begin
  1951.                 if (doarrow = 0) or
  1952.                         (tq^.tattr = areference) then
  1953.                     begin
  1954.                     write('(*');
  1955.                     printid(tp^.tsym^.lid);
  1956.                     write(')')
  1957.                     end
  1958.                 else begin
  1959.                     printid(tp^.tsym^.lid);
  1960.                     write('->');
  1961.                     donearr := true
  1962.                      end
  1963.                 end
  1964.             else if (tq^.tt = nconst) and conflag then
  1965.                 write(cvalof(tp):1)
  1966.             else if tq^.tt in [nparproc, nparfunc] then
  1967.                 begin
  1968.                 write('(*');
  1969.                 printid(tp^.tsym^.lid);
  1970.                 write(')')
  1971.                 end
  1972.             else
  1973.                 printid(tp^.tsym^.lid);
  1974.             end;
  1975.           nchar:
  1976.             printchr(tp^.tsym^.lchar);
  1977.           ninteger:
  1978.             write(tp^.tsym^.linum:1);
  1979.           nreal:
  1980.             printtok(tp^.tsym^.lfloat);
  1981.           nstring:
  1982.             printstr(tp^.tsym^.lstr);
  1983.           nset:
  1984.             if constset(tp^.texps) then
  1985.                 begin
  1986.                 (* save set expression for initialization *)
  1987.                 write('Conset[', setcnt:1, ']');
  1988.                 setcnt := setcnt + 1;
  1989.                 tq := mknode(nset);
  1990.                 tq^.tnext := setlst;
  1991.                 setlst := tq;
  1992.                 tq^.texps := tp^.texps
  1993.                 end
  1994.             else begin
  1995.                 increment;
  1996.                 flag := dropset;
  1997.                 (* if a set-constructor is used in an
  1998.                    expression involving + - *  it will need to
  1999.                    be saved temporarily (by Saveset) but often
  2000.                    we can simply forget the set-value when we
  2001.                    have finished using it *)
  2002.                 if dropset then
  2003.                     dropset := false
  2004.                 else
  2005.                     write('Saveset(');
  2006.                 write('(Tmpset = Newset(), ');
  2007.                 tq := tp^.texps;
  2008.                 while tq <> nil do
  2009.                     begin
  2010.                     case tq^.tt of
  2011.                       nrange:
  2012.                         begin
  2013.                         usemksub := true;
  2014.                         write(voidcast, 'Mksubr(');
  2015.                         write('(unsigned)(');
  2016.                         eexpr(tq^.texpl);
  2017.                         write('), ');
  2018.                         write('(unsigned)(');
  2019.                         eexpr(tq^.texpr);
  2020.                         write('), Tmpset)')
  2021.                         end;
  2022.                       nin, neq, nne, nlt, nle, ngt, nge,
  2023.                       nor, nand, nmul, ndiv, nmod, nquot,
  2024.                       nplus, nminus, nnot, numinus, nuplus, 
  2025.                       nindex, nselect, nderef, ncall,
  2026.                       ninteger, nchar, nid:
  2027.                         begin
  2028.                         useins := true;
  2029.                         write(voidcast, 'Insmem(');
  2030.                         write('(unsigned)(');
  2031.                         eexpr(tq);
  2032.                         write('), Tmpset)')
  2033.                         end
  2034.                     end;(* case *)
  2035.                     tq := tq^.tnext;
  2036.                     if tq <> nil then
  2037.                         begin
  2038.                         writeln(',');
  2039.                         indent
  2040.                         end
  2041.                     end;
  2042.                 write(', Tmpset)');
  2043.                 if not flag then
  2044.                     begin
  2045.                     write(')');
  2046.                     setused := true
  2047.                     end;
  2048.                 decrement
  2049.                  end;
  2050.           nnil:
  2051.             begin
  2052.             tq := tp;
  2053.             repeat
  2054.                 tq := tq^.tup
  2055.             until    tq^.tt in [neq, nne, ncall, nassign, npgm];
  2056.             if tq^.tt in [neq, nne] then
  2057.                 begin
  2058.                 if typeof(tq^.texpl) = typnods[tnil] then
  2059.                     tq := typeof(tq^.texpr)
  2060.                 else
  2061.                     tq := typeof(tq^.texpl);
  2062.                 if tq^.tt = nptr then
  2063.                     begin
  2064.                     write('(');
  2065.                     etypedef(tq);
  2066.                     write(')')
  2067.                     end
  2068.                 end;
  2069.             write('NIL')
  2070.             end;
  2071.         end;(* case *)
  2072.     999:
  2073.     end;    (* eexpr *)
  2074.  
  2075.     (*    Emit constant definitions.                *)
  2076.     procedure econst(tp : treeptr);
  2077.  
  2078.     var    sp    : symptr;
  2079.  
  2080.     begin
  2081.         while tp <> nil do
  2082.             begin
  2083.             sp := tp^.tidl^.tsym;
  2084.             if sp^.lid^.inref > 1 then
  2085.                 sp^.lid := mkrename('X', sp^.lid);
  2086.             if tp^.tbind^.tt = nstring then
  2087.                 begin
  2088.                 (* string constants emitted as
  2089.                    static local variables *)
  2090.                 indent;
  2091.                 write(static, chartyp, tab1);
  2092.                 printid(sp^.lid);
  2093.                 write('[]    = ');
  2094.                 eexpr(tp^.tbind);
  2095.                 writeln(';')
  2096.                 end
  2097.             else begin
  2098.                 (* all other constants emitted as
  2099.                    preprocessor # defines *)
  2100.                 write(define);
  2101.                 printid(sp^.lid);
  2102.                 write(space);
  2103.                 eexpr(tp^.tbind);
  2104.                 writeln
  2105.                 end;
  2106.             tp := tp^.tnext
  2107.             end
  2108.     end;    (* econst *)
  2109.  
  2110.     (*    Emit a typedef.                        *)
  2111.     procedure etypedef;
  2112.  
  2113.         (*    Workhorse for etypedef, this procedure also    *)
  2114.         (*    renames all fields in record-unions when    *)
  2115.         (*    necessary.                    *)
  2116.         procedure etdef(uid : idptr; tp : treeptr);
  2117.  
  2118.         var    i    : integer;
  2119.             tq    : treeptr;
  2120.  
  2121.             (*    Emit definition for an integer subrange    *)
  2122.             (*    using data from worddefs set up during    *)
  2123.             (*    initialization.                *)
  2124.             procedure etrange(tp : treeptr);
  2125.  
  2126.             label    999;
  2127.  
  2128.             var    lo, hi    : integer;
  2129.                 i    : 1 .. maxmachdefs;
  2130.  
  2131.             begin
  2132.                 lo := clower(tp);
  2133.                 hi := cupper(tp);
  2134.                 (* scan CPU word definitions for a type
  2135.                    enclosing wanted range *)
  2136.                 for i := 1 to nmachdefs do
  2137.                     with machdefs[i] do
  2138.                     if (lo >= lolim) and (hi <= hilim) then
  2139.                         begin
  2140.                         (* found it, print type name *)
  2141.                         printtok(typstr);
  2142.                         goto 999
  2143.                         end;
  2144.                 fatal(erange);
  2145.             999:
  2146.             end;
  2147.  
  2148.             (*    Print last component of identifier.    *)
  2149.             procedure printsuf(ip : idptr);
  2150.  
  2151.             var    w    : toknbuf;
  2152.                 i, j    : toknidx;
  2153.  
  2154.             begin
  2155.                 gettokn(ip^.istr, w);
  2156.                 i := 1;
  2157.                 j := i;
  2158.                 while w[i] <> chr(null) do
  2159.                     begin
  2160.                     if w[i] = '.' then
  2161.                         j := i;
  2162.                     i := i + 1
  2163.                     end;
  2164.                 if w[j] = '.' then
  2165.                     j := j + 1;
  2166.                 while w[j] <> chr(null) do
  2167.                     begin
  2168.                     write(w[j]);
  2169.                     j := j + 1
  2170.                     end
  2171.             end;
  2172.  
  2173.         begin    (* etdef *)
  2174.             case tp^.tt of
  2175.               nid:
  2176.                 printid(tp^.tsym^.lid);
  2177.               nptr:
  2178.                 begin
  2179.                 tq := typeof(tp^.tptrid);
  2180.                 if tq^.tt = nrecord then
  2181.                     begin
  2182.                     write('struct ');
  2183.                     printid(tq^.tuid)
  2184.                     end
  2185.                 else
  2186.                     printid(tp^.tptrid^.tsym^.lid);
  2187.                 write(' *');
  2188.                 end;
  2189.               nscalar:
  2190.                 begin
  2191.                 write('enum { ');
  2192.                 increment;
  2193.                 tp := tp^.tscalid;
  2194.  
  2195.                 (* avoid bug in C-compiler:
  2196.                        enums are mixed in same namespace *)
  2197.                 if tp^.tsym^.lid^.inref > 1 then
  2198.                     tp^.tsym^.lid :=
  2199.                         mkrename('E', tp^.tsym^.lid);
  2200.                 printid(tp^.tsym^.lid);
  2201.                 i := 1;
  2202.                 while tp^.tnext <> nil do
  2203.                     begin
  2204.                     if i >= 4 then
  2205.                         begin
  2206.                         writeln(',');
  2207.                         indent;
  2208.                         i := 1
  2209.                         end
  2210.                     else begin
  2211.                         write(', ');
  2212.                         i := i + 1
  2213.                          end;
  2214.                     tp := tp^.tnext;
  2215.                     if tp^.tsym^.lid^.inref > 1 then
  2216.                         tp^.tsym^.lid :=
  2217.                         mkrename('E', tp^.tsym^.lid);
  2218.                     printid(tp^.tsym^.lid)
  2219.                     end;
  2220.                 decrement;
  2221.                 write(' } ')
  2222.                 end;
  2223.               nsubrange:
  2224.                 begin
  2225.                 tq := typeof(tp^.tlo);
  2226.                 if tq = typnods[tinteger] then
  2227.                     etrange(tp)
  2228.                 else begin
  2229.                     if tq^.tup^.tt = ntype then
  2230.                         tq := tq^.tup^.tidl;
  2231.                     etdef(nil, tq)
  2232.                      end
  2233.                 end;
  2234.               nfield:
  2235.                 begin
  2236.                 etdef(nil, tp^.tbind);
  2237.                 write(tab1);
  2238.                 tp := tp^.tidl;
  2239.                 if uid <> nil then
  2240.                     tp^.tsym^.lid :=
  2241.                         mkconc('.', uid, tp^.tsym^.lid);
  2242.                 printsuf(tp^.tsym^.lid);
  2243.                 i := 1;
  2244.                 while tp^.tnext <> nil do
  2245.                     begin
  2246.                     if i >= 4 then
  2247.                         begin
  2248.                         writeln(',');
  2249.                         indent;
  2250.                         write(tab1);
  2251.                         i := 1
  2252.                         end
  2253.                     else begin
  2254.                         write(', ');
  2255.                         i := i + 1
  2256.                          end;
  2257.                     tp := tp^.tnext;
  2258.                     if uid <> nil then
  2259.                         tp^.tsym^.lid :=
  2260.                         mkconc('.', uid, tp^.tsym^.lid);
  2261.                     printsuf(tp^.tsym^.lid);
  2262.                     end;
  2263.                 writeln(';');
  2264.                 end;
  2265.               nrecord:
  2266.                 begin
  2267.                 write('struct ');
  2268.                 if tp^.tuid = nil then
  2269.                     tp^.tuid := uid
  2270.                 else if uid = nil then
  2271.                     printid(tp^.tuid);
  2272.                 writeln(' {');
  2273.                 increment;
  2274.                 if (tp^.tflist = nil) and
  2275.                             (tp^.tvlist = nil) then
  2276.                     begin
  2277.                     (* C doesn't allow empty structures *)
  2278.                     indent;
  2279.                     writeln(inttyp, tab1, 'dummy;')
  2280.                     end;
  2281.                 tq := tp^.tflist;
  2282.                 while tq <> nil do
  2283.                     begin
  2284.                     indent;
  2285.                     etdef(uid, tq);
  2286.                     tq := tq^.tnext
  2287.                     end;
  2288.                 if tp^.tvlist <> nil then
  2289.                     begin
  2290.                     indent;
  2291.                     writeln('union {');
  2292.                     increment;
  2293.                     tq := tp^.tvlist;
  2294.                     while tq <> nil do
  2295.                         begin
  2296.                         if (tq^.tvrnt^.tflist <> nil) or
  2297.                          (tq^.tvrnt^.tvlist <> nil) then
  2298.                             begin
  2299.                             indent;
  2300.                             if uid = nil then
  2301.                                 etdef(mkvrnt,
  2302.                                 tq^.tvrnt)
  2303.                             else
  2304.                                 etdef(mkconc('.',
  2305.                                    uid, mkvrnt),
  2306.                                 tq^.tvrnt);
  2307.                             writeln(';')
  2308.                             end;
  2309.                         tq := tq^.tnext
  2310.                         end;
  2311.                     decrement;
  2312.                     indent;
  2313.                     writeln('} U;');
  2314.                     end;
  2315.                 decrement;
  2316.                 indent;
  2317.                 if tp^.tup^.tt = nvariant then
  2318.                     begin
  2319.                     write('} ');
  2320.                     printsuf(tp^.tuid)
  2321.                     end
  2322.                 else
  2323.                     write('}');
  2324.                 end;
  2325.               nconfarr:
  2326.                 begin
  2327.                 write('struct ');
  2328.                 printid(tp^.tcuid);
  2329.                 write(' { ');
  2330.                 etdef(nil, tp^.tcelem);
  2331.                 write(tab1, 'A[]; }')
  2332.                 end;
  2333.               narray:
  2334.                 begin
  2335.                 write('struct { ');
  2336.                 etdef(nil, tp^.taelem);
  2337.                 write(tab1, 'A[');
  2338.                 tq := typeof(tp^.taindx);
  2339.                 if tq^.tt = nsubrange then
  2340.                     begin
  2341.                     if arithexpr(tq^.thi) then
  2342.                         begin
  2343.                         eexpr(tq^.thi);
  2344.                         if cvalof(tq^.tlo) <> 0 then
  2345.                             begin
  2346.                             write(' - ');
  2347.                             eexpr(tq^.tlo)
  2348.                             end
  2349.                         end
  2350.                     else begin
  2351.                         write('(int)(');
  2352.                         eexpr(tq^.thi);
  2353.                         if cvalof(tq^.tlo) <> 0 then
  2354.                             begin
  2355.                             write(') - (int)(');
  2356.                             eexpr(tq^.tlo)
  2357.                             end;
  2358.                         write(')')
  2359.                          end;
  2360.                     write(' + 1')
  2361.                     end
  2362.                 else
  2363.                     write(crange(tp^.taindx):1);
  2364.                 write(']; }')
  2365.                 end;
  2366.               nfileof:
  2367.                 begin
  2368.                 writeln('struct {');
  2369.                 indent;
  2370.                 writeln(tab1, 'FILE', tab1, '*fp;');
  2371.                 indent;
  2372.                 writeln(tab1, filebits, tab1, 'eoln:1,');
  2373.                 indent;
  2374.                 writeln(tab3, 'eof:1,');
  2375.                 indent;
  2376.                 writeln(tab3, 'out:1,');
  2377.                 indent;
  2378.                 writeln(tab3, 'init:1,');
  2379.                 indent;
  2380.                 writeln(tab3, ':', filefill:1, ';');
  2381.                 indent;
  2382.                 write(tab1);
  2383.                 etdef(nil, tp^.tof);
  2384.                 writeln(tab1, 'buf;');
  2385.                 indent;
  2386.                 write('} ')
  2387.                 end;
  2388.               nsetof:
  2389.                 write('struct { ', setwtyp, tab1, 'S[',
  2390.                             csetsize(tp):1, ']; }');
  2391.               npredef:
  2392.                 begin
  2393.                 case tp^.tobtyp of
  2394.                   tboolean:
  2395.                     printid(defnams[dboolean]^.lid);
  2396.                   tchar:
  2397.                     write(chartyp);
  2398.                   tinteger:
  2399.                     printid(defnams[dinteger]^.lid);
  2400.                   treal:
  2401.                     printid(defnams[dreal]^.lid);
  2402.                   tstring:
  2403.                     write(chartyp, ' *');
  2404.                   ttext:
  2405.                     write('text');
  2406.                   tnil,
  2407.                   tset,
  2408.                   terror:
  2409.                     fatal(etree);
  2410.                   tnone:
  2411.                     write(voidtyp);
  2412.                 end (* case *)
  2413.                 end;
  2414.               nempty:
  2415.                 write(voidtyp);
  2416.             end;(* case *)
  2417.         end;    (* etdef *)
  2418.     begin
  2419.         etdef(nil, tp)
  2420.     end;    (* etypedef *)
  2421.  
  2422.     (*    Emit code for type declarations.            *)
  2423.     procedure etype(tp : treeptr);
  2424.  
  2425.     var    sp    : symptr;
  2426.  
  2427.     begin
  2428.         while tp <> nil do
  2429.             begin
  2430.             (* if identifier used more than once we rename the type
  2431.                to avoid typedef'ing an identifier twice *)
  2432.             sp := tp^.tidl^.tsym;
  2433.             if sp^.lid^.inref > 1 then
  2434.                 sp^.lid := mkrename('Y', sp^.lid);
  2435.             indent;
  2436.             write(typdef);
  2437.             etypedef(tp^.tbind);
  2438.             write(tab1);
  2439.             printid(sp^.lid);
  2440.             writeln(';');
  2441.             tp := tp^.tnext
  2442.             end
  2443.     end;
  2444.  
  2445.     (*    Emit code for variable declarations.            *)
  2446.     procedure evar(tp : treeptr);
  2447.  
  2448.     label    555;
  2449.  
  2450.     var    tq    : treeptr;
  2451.         i    : integer;
  2452.  
  2453.     begin
  2454.         while tp <> nil do
  2455.             begin
  2456.             indent;
  2457.             case tp^.tt of
  2458.               nvar,
  2459.               nvalpar,
  2460.               nvarpar:
  2461.                 begin
  2462.                 if tp^.tattr = aregister then
  2463.                     write(registr);
  2464.                 etypedef(tp^.tbind)
  2465.                 end;
  2466.               nparproc,
  2467.               nparfunc:
  2468.                 begin
  2469.                 if tp^.tt = nparproc then
  2470.                     write(voidtyp)
  2471.                 else
  2472.                     etypedef(tp^.tpartyp);
  2473.                 tq := tp^.tparid;
  2474.                 write(tab1, '(*');
  2475.                 printid(tq^.tsym^.lid);
  2476.                 write(')()');
  2477.                 goto 555
  2478.                 end
  2479.             end;(* case *)
  2480.             write(tab1);
  2481.             tq := tp^.tidl;
  2482.             i := 1;
  2483.             repeat
  2484.                 if tp^.tt = nvarpar then
  2485.                     write('*');
  2486.                 printid(tq^.tsym^.lid);
  2487.                 tq := tq^.tnext;
  2488.                 if tq <> nil then
  2489.                     begin
  2490.                     if i >= 6 then
  2491.                         begin
  2492.                         i := 1;
  2493.                         writeln(',');
  2494.                         indent;
  2495.                         write(tab1)
  2496.                         end
  2497.                     else begin
  2498.                         i := i + 1;
  2499.                         write(', ')
  2500.                          end
  2501.  
  2502.